package com.oocl.scan.jdt.parser;

import java.util.List;
import java.util.Map;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.CatchClause;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.ConditionalExpression;
import org.eclipse.jdt.core.dom.DoStatement;
import org.eclipse.jdt.core.dom.EnhancedForStatement;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.ForStatement;
import org.eclipse.jdt.core.dom.IfStatement;
import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.ParenthesizedExpression;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.SuperFieldAccess;
import org.eclipse.jdt.core.dom.SuperMethodInvocation;
import org.eclipse.jdt.core.dom.SwitchStatement;
import org.eclipse.jdt.core.dom.ThisExpression;
import org.eclipse.jdt.core.dom.TryStatement;
import org.eclipse.jdt.core.dom.TypeLiteral;
import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.core.dom.WhileStatement;

public class StatementParser {


  public void parseStatement(Statement statement, List<Statement> statementList, List<Expression> expressionList, Map<String, Object> variableMap) {
    if (statement instanceof Block) {
      for (Object blockObject : ((Block) statement).statements()) {
        parseStatement((Statement) blockObject, statementList, expressionList, variableMap);
      }
    } else if (statement instanceof IfStatement) {
      IfStatement ifStatement = (IfStatement) statement;
      parseExpression(ifStatement.getExpression(), expressionList);
      parseStatement(ifStatement.getThenStatement(), statementList, expressionList, variableMap);
      if (ifStatement.getElseStatement() != null) {
        parseStatement(ifStatement.getElseStatement(), statementList, expressionList, variableMap);
      }
    } else if (statement instanceof DoStatement) {
      DoStatement actualStatement = (DoStatement) statement;
      parseStatement(actualStatement.getBody(), statementList, expressionList, variableMap);
      parseExpression(actualStatement.getExpression(), expressionList);
    } else if (statement instanceof TryStatement) {
      TryStatement tryStatement = (TryStatement) statement;
      parseStatement(tryStatement.getBody(), statementList, expressionList, variableMap);
      parseStatement(tryStatement.getFinally(), statementList, expressionList, variableMap);
      for (Object obj : tryStatement.catchClauses()) {
        CatchClause catchClause = (CatchClause) obj;
        parseStatement(catchClause.getBody(), statementList, expressionList, variableMap);
      }
    } else if (statement instanceof ForStatement) {
      ForStatement forStatement = (ForStatement) statement;
      parseExpression(forStatement.getExpression(), expressionList);
      parseStatement(forStatement.getBody(), statementList, expressionList, variableMap);
    } else if (statement instanceof EnhancedForStatement) {
      EnhancedForStatement enhancedForStatement = (EnhancedForStatement) statement;
      String parameterType = enhancedForStatement.getParameter().getType().toString();
      String parameterName = enhancedForStatement.getParameter().toString().substring(enhancedForStatement.getParameter().toString().indexOf(" ") + 1);
      variableMap.put(parameterName, parameterType);
      parseStatement(enhancedForStatement.getBody(), statementList, expressionList, variableMap);
    } else if (statement instanceof SwitchStatement) {
      SwitchStatement switchStatement = (SwitchStatement) statement;
      parseExpression(switchStatement.getExpression(), expressionList);
      for (Object switchStatementObject : switchStatement.statements()) {
        parseStatement((Statement) switchStatementObject, statementList, expressionList, variableMap);
      }
    } else if (statement instanceof WhileStatement) {
      WhileStatement whileStatement = (WhileStatement) statement;
      parseExpression(whileStatement.getExpression(), expressionList);
      parseStatement(whileStatement.getBody(), statementList, expressionList, variableMap);
    } else if (statement instanceof ExpressionStatement) {
      parseExpression(((ExpressionStatement) statement).getExpression(), expressionList);
    } else if (statement instanceof VariableDeclarationStatement) {
      statementList.add(statement);
//      List<VariableDeclarationFragment> fragments = ((VariableDeclarationStatement) statement).fragments();
//      for (VariableDeclarationFragment frag : fragments) {
//        parseExpression(frag.getInitializer(), expressionList);
//      }
    } else if (statement instanceof ReturnStatement) {
      parseExpression(((ReturnStatement) statement).getExpression(), expressionList);
    } else {
      statementList.add(statement);
    }
  }

  public void parseExpression(Expression expression, List<Expression> expressionList) {
    if (expression == null || "\"\"".equals(expression.toString())) {
      return;
    }
    if (expression instanceof Assignment) {
      Assignment assignment = (Assignment) expression;
      parseExpression(assignment.getRightHandSide(),expressionList);
    } else if (expression instanceof ClassInstanceCreation) {
      parseExpression(((ClassInstanceCreation) expression).getExpression(), expressionList);
    } else if (expression instanceof ConditionalExpression) {
      ConditionalExpression actualExp = (ConditionalExpression) expression;
      parseExpression(actualExp.getExpression(), expressionList);
      parseExpression(actualExp.getThenExpression(), expressionList);
      parseExpression(actualExp.getElseExpression(), expressionList);
    } else if (expression instanceof MethodInvocation) {
      MethodInvocation methodInvocation = (MethodInvocation) expression;
      for (Object arg : methodInvocation.arguments()) {
        parseExpression((Expression) arg, expressionList);
      }
      expressionList.add(expression);
    } else if (expression instanceof StringLiteral) {
//      expressionList.add(expression);
    } else if (expression instanceof FieldAccess) {
//      expressionList.add(expression);
    } else if (expression instanceof SuperFieldAccess) {
//      expressionList.add(expression);
    } else if (expression instanceof SuperMethodInvocation) {
//      expressionList.add(expression);
    } else if (expression instanceof ThisExpression) {
//      expressionList.add(expression);
    } else if (expression instanceof TypeLiteral) {
//      expressionList.add(expression);
    } else if (expression instanceof VariableDeclarationExpression) {
      expressionList.add(expression);
    } else if (expression instanceof ClassInstanceCreation) {
//      expressionList.add(expression);
    } else if (expression instanceof InfixExpression) {
      if (((InfixExpression) expression).getOperator() != null) {
        parseExpression(((InfixExpression) expression).getLeftOperand(), expressionList);
        parseExpression(((InfixExpression) expression).getRightOperand(), expressionList);
      }
    } else if (expression instanceof ParenthesizedExpression) {
      parseExpression(((ParenthesizedExpression) expression).getExpression(), expressionList);
    } else if (expression instanceof QualifiedName) {
    } else if (expression instanceof MethodInvocation) {
      MethodInvocation actualExp = (MethodInvocation) expression;
      for (Object arg : actualExp.arguments()) {
        parseExpression((Expression) arg, expressionList);
      }
    }
  }
}
